package com.broad.commerce.code.services.business;

import com.broad.commerce.code.base.AbstractJavaService;
import com.broad.commerce.code.modules.BaseModule;
import com.broad.commerce.code.modules.business.ServiceModule;
import com.broad.commerce.common.utils.core.StringUtils;
import com.broad.commerce.web.exception.ServiceException;
import org.springframework.stereotype.Service;

/**
 * @author stephen
 * @version V1.0
 * @date 2022-02-08 18:54
 * @description: ControllerModuleService
 **/
@SuppressWarnings("DuplicatedCode")
@Service
public class ServiceModuleService extends AbstractJavaService {
	/**
	 * Create entity code string.
	 * @param baseModule the base module
	 * @return the string
	 */
	@Override
	public String createClassCode(BaseModule baseModule) {
		if (!(baseModule instanceof ServiceModule)) {
			throw new ServiceException("传入参数类型错误！应为 ServiceModule");
		}
		return super.createClassCode(baseModule);
	}

	/**
	 * Create import code.
	 * @param sb the sb
	 * @param baseModule the base module
	 */
	@Override
	protected void createImportCode(StringBuilder sb, BaseModule baseModule) {
		ServiceModule serviceModule = (ServiceModule) baseModule;
		//@off
		sb.append("import com.broad.commerce.common.utils.io.BeanUtils;\n")
		  .append("import ").append(serviceModule.getInterfaceFullClassName()).append(";\n")
		  .append("import ").append(serviceModule.getEntityFullClassName()).append(";\n")
		  .append("import ").append(serviceModule.getModelFullClassName()).append(";\n")
		  .append("import ").append(serviceModule.getMapperFullClassName()).append(";\n")
		  .append("import ").append(serviceModule.getJpaFullClassName()).append(";\n")
		  .append("import ").append(serviceModule.getMapperFullClassName()).append(";\n")
		  .append("import com.google.common.collect.Lists;").append("\n")
		  .append("import org.springframework.beans.factory.annotation.Autowired;").append("\n")
		  .append("import org.springframework.stereotype.Service;").append("\n")
		  .append("import org.springframework.transaction.annotation.Transactional;").append("\n")
		  .append("\n")
		  .append("import java.util.List;").append("\n")
		  .append("\n");//@on
	}

	/**
	 * Create annotation code.
	 * @param sb the sb
	 * @param baseModule the base module
	 */
	@Override
	protected void createAnnotationCode(StringBuilder sb, BaseModule baseModule) {
		sb.append("@Service\n");
	}

	/**
	 * Create class start tag.
	 * @param sb the sb
	 * @param baseModule the base module
	 */
	@Override
	protected void createClassStartTag(StringBuilder sb, BaseModule baseModule) {
		ServiceModule serviceModule = (ServiceModule) baseModule;
		//@off
		sb.append("public class ").append(serviceModule.getClassName()).append(" implements ")
		  .append(serviceModule.getInterfaceClassName())
		  .append(" {\n");//@on
	}

	/**
	 * Create class content.
	 * @param sb the sb
	 * @param baseModule the base module
	 * Student student = (Student)BeanUtils.parse(studentDTO, new Student());
	 * List<SystemMenu> systemMenus = Lists.newArrayList();
	 * systemMenuDTOs.forEach(systemMenuDTO -> {
	 * SystemMenu systemMenu = (SystemMenu) BeanUtils.parse(systemMenuDTO, new SystemMenu());
	 * systemMenus.add(systemMenu);
	 * });
	 */
	@Override
	protected void createClassContent(StringBuilder sb, BaseModule baseModule) {
		ServiceModule serviceModule = (ServiceModule) baseModule;
		this.createClassInjectionContent(sb, serviceModule);
		String entityName = serviceModule.getEntityClassName();
		String modelName = serviceModule.getModelClassName();
		String entityInstance = StringUtils.lowerFirst(entityName);
		String modelInstance = StringUtils.lowerFirst(modelName);
		String jpaName = StringUtils.lowerFirst(serviceModule.getJpaClassName());
		String mybatisName = StringUtils.lowerFirst(serviceModule.getMapperClassName());
		//@off 查询所有
		sb.append("\t").append("@Override\n")
		  .append("\t").append("public List<").append(entityName).append("> selectAll() {\n")
		  .append("\t\t").append("return this.").append(mybatisName).append(".selectAll();\n")
		  .append("\t}\n\n");
		//查询单个数据
		sb.append("\t").append("@Override\n")
		  .append("\t").append("public ").append(entityName).append(" findOne(Long id) {\n")
		  .append("\t\t").append("return this.").append(jpaName).append(".findById(id).orElse(null);\n")
		  .append("\t}\n\n");
		//插入单个数据
		sb.append("\t").append("@Override\n")
		  .append("\t").append("@Transactional(rollbackFor = Exception.class)\n")
		  .append("\t").append("public ").append(entityName).append(" ").append("save(").append(modelName).append(" ").append(modelInstance).append(") {\n")
		  .append("\t\t").append(entityName).append(" ").append(entityInstance).append(";\n")
		  .append("\t\t").append("if (").append(modelInstance).append(".getId() == null) {\n")
		  .append("\t\t\t").append(entityInstance).append(" = BeanUtils.parse(").append(modelInstance).append(", ").append(entityName).append(".class);\n")
		  .append("\t\t").append("} else {\n")
		  .append("\t\t\t").append(entityInstance).append(" = this.findOne(").append(modelInstance).append(".getId());\n")
		  .append("\t\t\t").append("BeanUtils.parse(").append(modelInstance).append(", ").append(entityInstance).append(");\n")
		  .append("\t\t").append("}\n")
		  .append("\t\t").append("return this.").append(jpaName).append(".saveAndFlush(").append(entityInstance).append(");\n")
		  .append("\t}\n\n");
		//批量插入数据
		sb.append("\t").append("@Override\n")
		  .append("\t").append("@Transactional(rollbackFor = Exception.class)\n")
		  .append("\t").append("public void ").append("saveAll(List<").append(modelName).append("> ").append(modelInstance).append("S) {\n")
		  .append("\t\t").append(modelInstance).append("S.forEach(this::save);\n")
		  .append("\t}\n\n");
		//删除单个数据
		sb.append("\t").append("@Override\n")
		  .append("\t").append("@Transactional(rollbackFor = Exception.class)\n")
		  .append("\t").append("public void delete(Long id) {\n")
		  .append("\t\t").append("this.").append(jpaName).append(".deleteById(id);\n")
		  .append("\t}\n");//@on
	}

	/**
	 * Create class injection content.
	 * @param sb the sb
	 * @param baseModule the base module
	 */
	private void createClassInjectionContent(StringBuilder sb, ServiceModule serviceModule) {
		//@off
		sb.append("\t").append("@Autowired").append("\n")
		  .append("\t").append("private ").append(serviceModule.getJpaClassName()).append(" ")
		  .append(StringUtils.lowerFirst(serviceModule.getJpaClassName())).append(";\n")
		  .append("\t").append("@Autowired").append("\n")
		  .append("\t").append("private ").append(serviceModule.getMapperClassName()).append(" ")
		  .append(StringUtils.lowerFirst(serviceModule.getMapperClassName())).append(";\n")
		  .append("\n");//@on
	}
}
